/* 
	definitions for SPU page mechanism
*/

#ifndef __SPU_PAGE_LAYOUT_H
#define __SPU_PAGE_LAYOUT_H
#pragma once

//temp define to support 2 guids in elf
//#define DEBUG_HEADER_GUID_EXT_TEMP
//#include "BaseTypes.h"

#if defined(PS3) || defined(PAGE_GEN)

//namespace containing data structs for binary layout
//all is stored with big endianess (except for the binary data copied from the elf itself)
namespace NPageBin
{
	inline const unsigned short EncodePageSize(const uint32 cOrigVal)
	{
		return (unsigned short)(cOrigVal >> 2);
	}

	inline const uint32 DecodePageSize(const unsigned short cOrigVal)
	{
		return ((uint32)cOrigVal) << 2;
	}

	/*binary layout of spu binary:
	header																  - bin header
	SJobStringHandle x num jobs						  - string and binary job offsets for each jobs
	Job String table (array of chars indexed into via SJobStringHandle's) - string table (just char array)
	Job binaries														- job binaries, must be 16 byte aligned
	Page directory: unsigned int x num pages	- offset for each page where to find
	SPage x num pages										- page binary itself, each page must be 128 byte aligned
	*/
	//header of binary
	struct SHeader
	{
		char PS3_BUILD_VERSION[32];			// id used to match the right spu repository to the right binary
		unsigned int spuDriverSize;			// size of the SPUDriver
		unsigned int jobStringOff;			//offset of string table start
		unsigned int funcProfStringOff;	//offset of profiling section string table start
		unsigned int funcProfStringIndOff;//offset of profiling section string table indices start
		unsigned int funcProfAreaSize;	//size to allocate for function profile timings
		unsigned int funcProfCount;			//number of function profiler entries
		unsigned int jobOff;						//offset of job binary start
		unsigned int pageOff;						//offset of page directory start
		unsigned short pageNum;					//number of pages contained
		unsigned short jobNum;					//number of jobs contained
	};

	//struct which will be used to map a job to a handle (which will be the address of the corresponding SJob entry))
	struct SJobStringHandle
	{
		unsigned int jobEntryOffset;		//offset job in binary (total offset)
		unsigned int jobStringStart;		//offset of string table in binary
		unsigned int jobStringSize;			//size of string (num chars)
	};

	//binary representation of a job
	struct SJob
	{
		unsigned short totalJobSize;		//total size of job in 4 bytes (header plus executable code and function table size) (size >> 2)
		short initialPages[4];					//id of first 4 pages, entry point points into initialPages[0], other might be -1
		unsigned short destPageOff;			//relative offset of the entry point into the first page (in 4 byte units)
		unsigned short branchOff;				//offset of the branch (relative to the job start (not text start)) (in 4 byte units)
		unsigned short bhOff;						//offset of the branch hint (relative to the job start (not text start)) (in 4 byte units)

		unsigned short funcTableOffset;	//offset of the function table relative to SJob, 0 if funcTableEntryCount = 0
		unsigned short funcTableEntryCount;//number of entries in function table
		unsigned short funcTableDebugOffset;//offset of the function table PPU addresses relative to SJob, will be same as funcTableOffset if not present
		unsigned short pageMode;				//page mode set by JobGen, encoded in upper 2 bite, lower bits contain max page size
		unsigned short bssOffset;				//offset of bss relative to job start (in multiple of 16 bytes)
		unsigned short bssSize;					//size of bss(in multiple of 16 bytes)
		unsigned short funcTableBinOff;	//binary offset of function table (without bss), in multiple of 4 bytes
		unsigned short funcTableSize;		//function table size, in multiple of 4 bytes

		unsigned short funcProfCount;		//number of function profile sections
		unsigned short funcProfIndStart;//index string table starts for function profile sections
		unsigned short funcProfTimingOff128;//offset for job timing area in cacheline units(allocated at startup)
		unsigned short pad0;

		unsigned int	 jobNameEA;				//set up during loading to map from SJob to its name
		unsigned short pad1[2];

		static const unsigned int scPageModeMask	= (1<<15 | 1<<14);
		static const unsigned int scPageModeShift = (14);
		unsigned int GetMaxPageSize(){return (pageMode & ~scPageModeMask) * 128;}
		unsigned int GetPageMode(){return (pageMode & scPageModeMask) >> scPageModeShift;}
		void SetMaxPageSize(const unsigned int cMaxSize){pageMode &= scPageModeMask; pageMode |= (unsigned short)(cMaxSize / 128);}
		void SetPageMode(const unsigned int cPageMode){pageMode &= ~scPageModeMask; pageMode |= (unsigned short)((unsigned int)cPageMode << scPageModeShift);}
		//here follows the executable text
		//	followed by the function pointer table
	} 



	;	
	//cross page entry header (all cross page entries belonging to the same ID)
	//required for fast indexing (during patching)
	//do not increase size, the sizeof value is used as shift in SetActivePages
/*	struct SCrossEntry
	{
		unsigned short destPageId;	//ID of dest page id of where function can be found (global for all pages)
		unsigned short numEntries;		//number of cross page entries
		unsigned short offset;				//offset of cross page entries relative to page binary start
		unsigned short pad;
		//the SPatchEntryBase entries follow here
	};
*/
	//header for binary representation of pages
	struct SPage
	{
		unsigned int size;								//size of whole page
		unsigned short segOff;						//offset of segment text relative to page start
		unsigned short crossCallPageNum;	//number of different pages for cross page call destinations (number of SCrossEntry's)
	};

	//since cross calls can only exist in a multi page environment, unsigned short suffices for any text offset (max 32 KB)
	//16 bytes are necessary to load the entire contents at once
	//never change order, it is accessed in asm via rotations
	//keep order in sync with SReturnStackEntry in SPUPages.h
	struct SCrossPatch
	{
		unsigned short pad0;					//was: unsigned short textOffset;		//source offset of cross page branch within text section of current page
		unsigned short sourcePageID;	//source page ID, required for fast access in miss handler
		unsigned short pad1;					//was: unsigned short bhTextOffset;	//difference to textOffset in bytes is also used for creating the branch instr.itself
		unsigned short destOffset;		//branch target offset in destination page (relative to its page start)

		unsigned short destPageID;		//destination page ID, required for fast access in miss handler
		unsigned short pad[3];

//		static const unsigned short scNoEntry = 0xFFFF;
		static const unsigned short scMaxPageID = 0x7FFF;
		static const unsigned short scWeak			  = 0x8000;



	};


} //NPageBin

#endif //PS3
#endif //__SPU_PAGE_LAYOUT_H
